﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using EntityAop.Configuration;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using RrslLite.Configuration;

namespace App.Test.Silverlight
{
    [TestClass]
    public class EntityAopTEST
    {
        private static ClassToBeProxied GetInstanceToBeProxied()
        {
            var instanceToBeProxied = new ClassToBeProxied();

            instanceToBeProxied.PropertyToBeProxied = "some";

            instanceToBeProxied.MemberClassToBeProxied =
                new MemberClassToBeProxied() { PropertyToBeProxied = "some" };

            instanceToBeProxied.MemberClassToBeProxiedIList =
                new List<MemberClassToBeProxied>()
                    {
                        new MemberClassToBeProxied(){ PropertyToBeProxied = "some1"},
                        new MemberClassToBeProxied(){ PropertyToBeProxied = "some2"},
                        new MemberClassToBeProxied(){ PropertyToBeProxied = "some3"}
                    };

            return instanceToBeProxied;
        }

        private static ClassToBeProxied GetProxiedInstance()
        {
            var proxyGenerator = new EntityAop.ProxyGenerator();

            var instanceToBeProxied = GetInstanceToBeProxied();

            var proxiedInstance = EntityAopConfiguration.Instance.CreateProxiedInstance(instanceToBeProxied);

           return proxiedInstance;
        }

        [TestInitialize]
        public void Init()
        {
            RrslLiteConfiguration.Instance
                .WithDefaultBatchBuilderConfiguration()
                    .BatchBuilderConfiguration
                        .WithCreateClassProxyWithTargetRecursiveToReceiveMessages()
                        .WithINotifyPropertyChangedInterceptorToReceiveMessages();
        }

        [TestMethod]
        public void EntityAop_CreateProxy()
        {
            var proxiedInstance = GetProxiedInstance();

            Assert.IsNotNull(proxiedInstance);

            Assert.IsNotNull(proxiedInstance.PropertyToBeProxied);
            Assert.IsNotNull(proxiedInstance.MemberClassToBeProxied);
            Assert.IsNotNull(proxiedInstance.MemberClassToBeProxiedIList);

            var instanceAsNotifyPropertyChanged = proxiedInstance as INotifyPropertyChanged;

            Assert.IsNotNull(instanceAsNotifyPropertyChanged);

            var propertyWasChanged = false;

            var newValue = "some new value";

            instanceAsNotifyPropertyChanged.PropertyChanged +=
                (s, e) =>
                {
                    
                    propertyWasChanged = true;
                };

            proxiedInstance.PropertyToBeProxied = newValue;

            Assert.IsTrue(propertyWasChanged);
        }

        [TestMethod]
        public void EntityAop_CreateProxy_And_Check_NonPrimitive_Properties_Are_Proxies_Also()
        {
            var proxiedInstance = GetProxiedInstance();

            var memberInstanceAsNotifyPropertyChanged = proxiedInstance.MemberClassToBeProxied as INotifyPropertyChanged;

            Assert.IsNotNull(memberInstanceAsNotifyPropertyChanged);
        }

        [TestMethod]
        public void EntityAop_CreateProxy_And_Check_Collection_Properties_Are_Proxies()
        {
            var proxiedInstance = GetProxiedInstance();

            var memberClassToBeProxiedIList = proxiedInstance.MemberClassToBeProxiedIList as INotifyPropertyChanged;

            Assert.IsNotNull(memberClassToBeProxiedIList);

            var itemInListAsINotifyPropertyChanged = proxiedInstance.MemberClassToBeProxiedIList.First() as INotifyPropertyChanged;

            Assert.IsNotNull(itemInListAsINotifyPropertyChanged);
        }

        public class ClassToBeProxied
        {
            public virtual string PropertyToBeProxied { get; set; }

            public virtual MemberClassToBeProxied MemberClassToBeProxied { get; set; }

            public virtual IList<MemberClassToBeProxied> MemberClassToBeProxiedIList { get; set; }
        }

        public class MemberClassToBeProxied
        {
            public virtual string PropertyToBeProxied { get; set; }
        }
    }
}
